import { IDashboardStore } from '@/core/interface/widgets/store';
import { DECtrlController } from './de-ctrl-controller';
import {
	DashboardActionType,
	IAbility,
	ICtrlActionResult,
	IDashboardAbility,
	IDashboardController,
	IDashboardControllerParams,
	IMDCtrlAbility,
	IParam,
} from '../../interface';
import { deepCopy } from '@/core/utils';

/**
 * 数据看板部件控制器
 *
 * @export
 * @class DashboardController
 * @extends {WidgetsController<IDashboardStore>}
 * @implements {IDashboardController}
 * @template T
 */
export class DashboardController
	extends DECtrlController<
		DashboardActionType,
		IDashboardStore,
		IDashboardAbility
	>
	implements IDashboardController<IDashboardStore, IDashboardAbility>
{
	/**
	 * Creates an instance of DashboardController.
	 * @param {IDashboardControllerParams<DashboardActionType, IDashboardAbility>} params
	 * @memberof DashboardController
	 */
	public constructor(
		params: IDashboardControllerParams<DashboardActionType, IDashboardAbility>
	) {
		super(params);
		this.ctrlInit(params);
	}

	/**
	 * 处理部件初始化
	 *
	 * @protected
	 * @param {IDashboardControllerParams<DashboardActionType, IDashboardAbility>} params
	 * @memberof DashboardController
	 */
	protected processCtrlInit(
		params: IDashboardControllerParams<DashboardActionType, IDashboardAbility>
	) {
		super.processCtrlInit(params);
		this.initPortletArray();
		Object.assign(this.store, { data: {} });
	}

	/**
	 * 初始化后（对store做处理）
	 *
	 * @protected
	 * @param {IDashboardControllerParams<DashboardActionType, IDashboardAbility>} params
	 * @memberof CtrlController
	 */
	protected afterCtrlInit(
		params: IDashboardControllerParams<DashboardActionType, IDashboardAbility>
	) {
		this.initStore();
        this.evt.emit('ctrlInit', this.name, this.getAbility());
	}

	/**
	 * 门户部件数组
	 *
	 * @private
	 * @type {any[]}
	 * @memberof DashboardController
	 */
	private portletArray: any[] = [];

	/**
	 * 初始化门户部件数组
	 *
	 * @memberof DashboardController
	 */
	protected initPortletArray() {
		const { portletArray } = this.model;
		this.portletArray.push(...portletArray);
	}

	/**
	 * 设置子能力
	 *
	 * @param {string} name
	 * @param {IAbility} subAbility
	 * @memberof DashboardController
	 */
	public setSubAbility(name: string, subAbility: IAbility) {
		this.subAbilityCenter.set(name, subAbility);
		if (this.subAbilityCenter.size == this.portletArray.length) {
			this.evt.emit('ctrlInit', this.name, this.getAbility());
		}
	}

	/**
	 * 加载子部件
	 *
	 * @memberof DashboardController
	 */
	public async load(opts: IParam = {}): Promise<ICtrlActionResult> {
		return new Promise(async (resolve: any, reject: any) => {
			const { context, viewParams } = this.store;
			const arg: any = { ...opts };
			Object.assign(arg, viewParams);
			const tempContext = deepCopy(context);
			const promiseArray: any = [];
			// 如果是实体dashboard部件，先去加载自身数据
			const { entityCodeName } = this.model;
			if (entityCodeName && tempContext[entityCodeName.toLowerCase()]) {
				const appEntityService = await App.getDataService(
					this.model.entityCodeName
				);
				promiseArray.push(appEntityService['Get'](tempContext, arg));
			}
			// 加载子portlet数据
			this.portletArray.forEach((item: any) => {
				const ability = this.getPortletCtrlAbility(item.name.toLowerCase());
				if (ability) {
					const promise = ability.load(arg);
					promiseArray.push(promise);
				}
			});
			this.beforeAsyncAction('load', tempContext, {});
			Promise.all(promiseArray)
				.then((resArray: any) => {
					const _data: any = [];
					resArray.forEach((response: any, resIndex: number) => {
						if (!response || !response.ok) {
							this.afterAsyncAction('load', response, { showResultInfo :false });
							return;
						}
						//	只有存在数据主键时才加载并附加数据
						if (
							resIndex == 0 &&
							entityCodeName &&
							tempContext[entityCodeName.toLowerCase()]
						) {
							this.store.data = response.data;
						} else {
							_data.push(response.rowData);
						}
					});
					const result = { ok: true, data: this.getData(), rowData: _data };
					this.emit('load', this.getData());
					this.afterAsyncAction('load', _data, { showResultInfo :false });
					resolve(result);
				})
				.catch((response: any) => {
					reject(response);
				});
		});
	}

	/**
	 * 计算暴露数据
	 *
	 * @protected
	 * @return {*}  {(IMDCtrlAbility)}
	 * @memberof DashboardController
	 */
	protected computeExposeData(
		data: IParam | Array<IParam>,
		targetData: Array<IParam>
	) {
		targetData.push(data);
		return targetData;
	}

	/**
	 * 获取门户部件能力
	 *
	 * @protected
	 * @return {*}  {(IMDCtrlAbility)}
	 * @memberof DashboardController
	 */
	protected getPortletCtrlAbility(name: string): IMDCtrlAbility {
		return this.getSubAbility<IMDCtrlAbility>(name);
	}

	/**
	 * @description 获取能力
	 * @return {*}  {IDashboardAbility}
	 * @memberof DashboardController
	 */
	public getAbility(): IDashboardAbility {
		return {
			...super.getAbility(),
			load: this.load.bind(this),
		};
	}
}
